﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Threading;
using System.Threading.Tasks;

namespace Sustainalytics.Utils
{
    public static class ParallelHelper
    {
        public static bool RunInParallel(this IEnumerable<Action> actions, int paralelismDegree = -1)
        {
            return RunInParallel(actions, new CancellationToken(), paralelismDegree);
        }

        public static bool RunInParallel(this IEnumerable<Action> actions, CancellationToken cancelToken, int paralelismDegree = -1)
        {
            if (paralelismDegree == -1)
                paralelismDegree = Environment.ProcessorCount;

            var options = new ParallelOptions { MaxDegreeOfParallelism = paralelismDegree, CancellationToken = cancelToken};
            
            var exceptions = new ConcurrentQueue<Exception>();
            Parallel.ForEach(actions, options, inputAction =>
            {
                try
                {
                    inputAction();
                }
                catch (Exception ex)
                {
                    exceptions.Enqueue(ex);
                }
            });

            if (exceptions.Count > 0)
            {
                var aex = (new AggregateException(exceptions)).Flatten();
                
                CommonEventSource.Log.Exception(aex);

                throw aex;
            }
            //todo rocket: should not return true in all cases, missleading 
            return true;
        }



        public static int GetMaxDegreeOfParallelism()
        {
            var maxDegreeOfParallelism = Environment.ProcessorCount;
            if (ConfigurationManager.AppSettings["MaxDegreeOfParallelism"] != null)
            {
                maxDegreeOfParallelism = Convert.ToInt32(ConfigurationManager.AppSettings["MaxDegreeOfParallelism"]);
            }
            return maxDegreeOfParallelism;
        }
    }
}
